package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotUpdateException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectFinishApplyService{

	@Autowired
	private ProjectFinishApplyDao projectFinishApplyDao;
	
	private QProjectFinishApply $ = QProjectFinishApply.projectFinishApply;
	
	@Autowired
	public void setProjectFinishApplyDao(ProjectFinishApplyDao projectFinishApplyDao) {
		this.projectFinishApplyDao = projectFinishApplyDao;
	}

	@Autowired
	private ProjectStakeholderDao projectStakeholderDao;
	
	private QProjectStakeholder $_projectStakeholder = QProjectStakeholder.projectStakeholder;
	
	@Autowired
	public void setProjectStakeholderDao(ProjectStakeholderDao projectStakeholderDao) {
		this.projectStakeholderDao = projectStakeholderDao;
	}

	@Autowired
	private ProjectDao projectDao;
	
	private QProject $_project = QProject.project;
	
	@Autowired
	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}
	
	public List<ProjectFinishApply> findAll(){
		return ListUtil.toList(projectFinishApplyDao.findAll());
	}
				
	public List<ProjectFinishApply> findAll(
	Long projectId,
	Long applyPersonId,
	String applyReason,
	Date applyTimeBegin,
	Date applyTimeEnd,
	Long checkPersonId,
	String checkDescription,
	Date checkTimeBegin,
	Date checkTimeEnd,
	Long ratifyPersonId,
	String ratifyDescription,
	Date ratifyTimeBegin,
	Date ratifyTimeEnd,
	String status,
	String orderByAttribute	){
	BooleanBuilder condition = new BooleanBuilder();
	
	if(IdUtil.isNotEmpty(projectId)){
		condition.and($.project.id.eq(projectId));
	}
	
	if(IdUtil.isNotEmpty(applyPersonId)){
		condition.and($.applyPerson.id.eq(applyPersonId));
	}
	
	if(StringUtil.isNotEmpty(applyReason)){
		condition.and($.applyReason.contains(applyReason));
	}
	
	if(applyTimeBegin != null){
		condition.and($.applyTime.after(applyTimeBegin));
	}
	
	if(applyTimeEnd != null){
		condition.and($.applyTime.before(applyTimeEnd));
	}
	
	if(IdUtil.isNotEmpty(checkPersonId)){
		condition.and($.checkPerson.id.eq(checkPersonId));
	}
	
	if(StringUtil.isNotEmpty(checkDescription)){
		condition.and($.checkDescription.contains(checkDescription));
	}
	
	if(checkTimeBegin != null){
		condition.and($.checkTime.after(checkTimeBegin));
	}
	
	if(checkTimeEnd != null){
		condition.and($.checkTime.before(checkTimeEnd));
	}
	
	if(IdUtil.isNotEmpty(ratifyPersonId)){
		condition.and($.ratifyPerson.id.eq(ratifyPersonId));
	}
	
	if(StringUtil.isNotEmpty(ratifyDescription)){
		condition.and($.ratifyDescription.contains(ratifyDescription));
	}
	
	if(ratifyTimeBegin != null){
		condition.and($.ratifyTime.after(ratifyTimeBegin));
	}
	
	if(ratifyTimeEnd != null){
		condition.and($.ratifyTime.before(ratifyTimeEnd));
	}
	
	if(StringUtil.isNotEmpty(status)){
		condition.and($.status.contains(status));
	}
	
	
	return ListUtil.toList(projectFinishApplyDao.findAll(condition));
	}		

	public Page<ProjectFinishApply> findAll(
			Long projectId,
			Long applyPersonId,
			String applyReason,
			Date applyTimeBegin,
			Date applyTimeEnd,
			Long checkPersonId,
			String checkDescription,
			Date checkTimeBegin,
			Date checkTimeEnd,
			Long ratifyPersonId,
			String ratifyDescription,
			Date ratifyTimeBegin,
			Date ratifyTimeEnd,
			String status,
			int pageNumber, int pageSize,String sortAttribute,String orderDirection) {
			BooleanBuilder condition = new BooleanBuilder();
	
			if(IdUtil.isNotEmpty(projectId)){
				condition.and($.project.id.eq(projectId));
			}
			if(IdUtil.isNotEmpty(applyPersonId)){
				condition.and($.applyPerson.id.eq(applyPersonId));
			}
			if(StringUtil.isNotEmpty(applyReason)){
				condition.and($.applyReason.contains(applyReason));
			}
			if(applyTimeBegin != null){
				condition.and($.applyTime.after(applyTimeBegin));
			}
			
			if(applyTimeEnd != null){
				condition.and($.applyTime.before(applyTimeEnd));
			}
			if(IdUtil.isNotEmpty(checkPersonId)){
				condition.and($.checkPerson.id.eq(checkPersonId));
			}
			if(StringUtil.isNotEmpty(checkDescription)){
				condition.and($.checkDescription.contains(checkDescription));
			}
			if(checkTimeBegin != null){
				condition.and($.checkTime.after(checkTimeBegin));
			}
			
			if(checkTimeEnd != null){
				condition.and($.checkTime.before(checkTimeEnd));
			}
			if(IdUtil.isNotEmpty(ratifyPersonId)){
				condition.and($.ratifyPerson.id.eq(ratifyPersonId));
			}
			if(StringUtil.isNotEmpty(ratifyDescription)){
				condition.and($.ratifyDescription.contains(ratifyDescription));
			}
			if(ratifyTimeBegin != null){
				condition.and($.ratifyTime.after(ratifyTimeBegin));
			}
			
			if(ratifyTimeEnd != null){
				condition.and($.ratifyTime.before(ratifyTimeEnd));
			}
			if(StringUtil.isNotEmpty(status)){
				condition.and($.status.contains(status));
			}
	
			Sort sortObject = null;
			if(StringUtil.isEmpty(sortAttribute)){
				sortObject = new Sort(Direction.DESC, "id");
			}else{
				sortObject = new Sort(Direction.fromStringOrNull(orderDirection),sortAttribute);
			}
			
			PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, sortObject);
			return projectFinishApplyDao.findAll(condition, pageRequest);
	}
	
	public ProjectFinishApply getProjectFinishApply(Long id){
		return projectFinishApplyDao.getOne(id);
	}
	
	public void deleteProjectFinishApply(Long id){
		projectFinishApplyDao.delete(id);
	}

	public void saveProjectFinishApply(ProjectFinishApply projectFinishApply) {
		if(null == projectFinishApply.getApplyTime()){
			projectFinishApply.setApplyTime(DateUtil.nowDate());
		}
		
		Project sourceProject = this.projectDao.findOne(projectFinishApply.getProject().getId());
		sourceProject.setStatus(projectFinishApply.getProject().getStatus());
		sourceProject.setConfirmationWorktime(sourceProject.getActualConsumeWorktime());
		sourceProject.setActualConsumeWorktime(projectFinishApply.getProject().getActualConsumeWorktime());
		
		this.projectFinishApplyDao.save(projectFinishApply);
		this.projectDao.save(sourceProject);
	}

	public List<ProjectFinishApply> findByStatus(People people, Long projectStakeholderType, String status) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectStakeholder.personID.eq(people.getId()));
		condition.and(this.$_projectStakeholder.projectStakeholderType.id.eq(projectStakeholderType));
		List<ProjectStakeholder> projectStakeholders = ListUtil.toList(this.projectStakeholderDao.findAll(condition));
		Set<Long> projectIds = new HashSet<Long>();
		for (ProjectStakeholder projectStakeholder : projectStakeholders) {
			projectIds.add(projectStakeholder.getProject().getId());
		}
		if(!projectIds.isEmpty()){
			condition = new BooleanBuilder();
			condition.and(this.$.project.id.in(projectIds));
			if(StringUtil.isNotEmpty(status)){
				condition.and($.status.eq(status));
			}
			return ListUtil.toList(projectFinishApplyDao.findAll(condition));
		}
		return null;
	}

	public boolean checkProjectDelayApplyRatify(ProjectFinishApply projectFinishApply) {
		ProjectFinishApply sourceProjectFinishApply = this.projectFinishApplyDao.findOne(projectFinishApply.getId());
		sourceProjectFinishApply.setRatifyDescription(projectFinishApply.getRatifyDescription());
		sourceProjectFinishApply.setStatus(projectFinishApply.getStatus());
		sourceProjectFinishApply.setRatifyTime(DateUtil.nowDate());
		sourceProjectFinishApply.setRatifyPerson(projectFinishApply.getRatifyPerson());

		//修改关联项目信息
		Project project = projectFinishApply.getProject();
		project.setActualFinishDate(DateUtil.nowDate());
		
		this.projectFinishApplyDao.save(sourceProjectFinishApply);
		this.projectDao.save(project);
		return true;
	}

	public void revocationFinishApplyProjectDelayApply(ProjectFinishApply projectFinishApply) throws CannotUpdateException {
		ProjectFinishApply sourceProjectFinishApply = this.projectFinishApplyDao.findOne(projectFinishApply.getId());
		if(!ProcessStatus.FINISH_APPLY.equals(sourceProjectFinishApply.getStatus())){
			throw new CannotUpdateException("项目完结申请已被处理，请刷新后再操作！");
		}
		sourceProjectFinishApply.setStatus(projectFinishApply.getStatus());
		sourceProjectFinishApply.setAnnulDate(DateUtil.nowDate());
		
		Project project = sourceProjectFinishApply.getProject();
		project.setStatus(projectFinishApply.getProject().getStatus());
		project.setActualConsumeWorktime(project.getConfirmationWorktime());
		project.setConfirmationWorktime(null);
		
		this.projectFinishApplyDao.save(sourceProjectFinishApply);
		this.projectDao.save(project);
	}

	public void checkProjectFinishApply(ProjectFinishApply projectFinishApply) throws CannotUpdateException {
		ProjectFinishApply sourceProjectFinishApply = this.projectFinishApplyDao.findOne(projectFinishApply.getId());
		if(!ProcessStatus.FINISH_APPLY.equals(sourceProjectFinishApply.getStatus())){
			throw new CannotUpdateException("项目完结申请发生变化，请刷新后再操作！");
		}
		sourceProjectFinishApply.setStatus(projectFinishApply.getStatus());
		sourceProjectFinishApply.setCheckTime(DateUtil.nowDate());
		sourceProjectFinishApply.setCheckPerson(projectFinishApply.getCheckPerson());
		sourceProjectFinishApply.setCheckDescription(projectFinishApply.getCheckDescription());
		
		Project project = sourceProjectFinishApply.getProject();
		if(ProcessStatus.EXAMINE_FAIL.equals(projectFinishApply.getStatus())){
			project.setActualConsumeWorktime(project.getConfirmationWorktime());
			project.setConfirmationWorktime(null);
		}
		project.setStatus(projectFinishApply.getProject().getStatus());
		
		this.projectFinishApplyDao.save(sourceProjectFinishApply);
		this.projectDao.save(project);
	}

	public void ratifyProjectFinishApply(ProjectFinishApply projectFinishApply) throws CannotUpdateException {
		ProjectFinishApply sourceProjectFinishApply = this.projectFinishApplyDao.findOne(projectFinishApply.getId());
		if(!ProcessStatus.EXAMINE_SUCCESS.equals(sourceProjectFinishApply.getStatus())){
			throw new CannotUpdateException("项目完结申请发生变化，请刷新后再操作！");
		}
		sourceProjectFinishApply.setRatifyPerson(projectFinishApply.getRatifyPerson());
		sourceProjectFinishApply.setRatifyDescription(projectFinishApply.getRatifyDescription());
		sourceProjectFinishApply.setRatifyTime(DateUtil.nowDate());
		sourceProjectFinishApply.setStatus(projectFinishApply.getStatus());
		
		Project project = sourceProjectFinishApply.getProject();
		if(ProcessStatus.VERIFY_FAIL.equals(projectFinishApply.getStatus())){
			project.setActualConsumeWorktime(project.getConfirmationWorktime());
			project.setConfirmationWorktime(null);
		}
		project.setStatus(projectFinishApply.getProject().getStatus());

		this.projectFinishApplyDao.save(sourceProjectFinishApply);
		this.projectDao.save(project);
	}

}
		
